﻿//
// Created by bxc on 2022/12/13.
//

#include "SipClient.h"
#include <stdio.h>
#include <string.h>

#include "Utils/Log.h"
#include "Utils/Utils.h"
#include "SipServerConfig.h"
#include "RtpSendPs.h"

#ifndef WIN32
// Linux系统
#include <arpa/inet.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#else
#include <WinSock2.h>
#pragma comment(lib, "ws2_32.lib")
#endif // !WIN32

extern "C" {
#include "Utils/HTTPDigest.h"
}

namespace BXC {

    SipClient::SipClient(SipServerConfig* serverConfig, SipClientConfig* clientConfig, const char* rtspurl)
        :mServerConfig(serverConfig), mClientConfig(clientConfig), mrtspurl(rtspurl),
        mRegistered(false), mRegisterId(-1) {

#ifdef WIN32
        WSADATA wsaData;
        if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)
        {
            LOGE("WSAStartup Error");
            return;
        }
#endif // WIN32


    }
    SipClient::~SipClient() {

#ifdef WIN32
        WSACleanup();
#endif // WIN32
        // 正式开始推流
        if (mRtpSendPs) {
            mRtpSendPs->stop();
            delete mRtpSendPs;
            mRtpSendPs = nullptr;
        }
        if (mSipCtx) {
            eXosip_quit(mSipCtx);
            osip_free(mSipCtx);
            mSipCtx = NULL;
        }
    }

    void SipClient::loop() {

        if (this->init_sip_client() != 0) {
            return;
        }

        SipClient* sipClient = this;
        static bool allowReg = true;


        int64_t lastKeepaliveTimestamp = 0;
        int64_t curTimestamp = 0;
        int64_t interval = 20000;// 客户端发送keepalive检测的间隔，单位：毫秒

        while (!sipClient->mClientConfig->quit) {

            // 首次发起注册
            if (allowReg && !sipClient->mRegistered) {
                allowReg = false;
                sipClient->request_register();
            }

            // 心跳机制 start （开发过程中，为防止影响抓包，可以先注释）
            if(sipClient->mRegistered){
                curTimestamp = getCurTimestamp();
                if(lastKeepaliveTimestamp == 0){
					sipClient->request_message_keepalive();
                    lastKeepaliveTimestamp = curTimestamp;
                } else {
                    if((curTimestamp - lastKeepaliveTimestamp) > interval){
                        sipClient->request_message_keepalive();
                        lastKeepaliveTimestamp = curTimestamp;
                    }
                }
            }
            // 心跳机制 end


            eXosip_event_t* evtp = eXosip_event_wait(sipClient->mSipCtx, 0, 200);
            if (!evtp) {
                eXosip_automatic_action(sipClient->mSipCtx);
                osip_usleep(100000);
                continue;
            }
			//eXosip_default_action(sipClient->mSipCtx, evtp);
            eXosip_automatic_action(sipClient->mSipCtx);
            sipClient->sip_event_handle(evtp);
            eXosip_event_free(evtp); // 释放
            static int i = 0;
            i++;
            if (i == 30)
                sipClient->mClientConfig->quit = true;
        }

    }

    int SipClient::init_sip_client() {

        mSipCtx = eXosip_malloc();
        if (!mSipCtx) {
            LOGE("new uas context error");
            return -1;
        }
        if (eXosip_init(mSipCtx)) {
            LOGE("exosip init error");
            return -1;
        }
        if (eXosip_listen_addr(mSipCtx, IPPROTO_UDP, NULL, mClientConfig->port, AF_INET, 0)) {
            LOGE("listen error");
            return -1;
        }
        eXosip_set_user_agent(mSipCtx, mClientConfig->ua);
        if (eXosip_add_authentication_info(mSipCtx, mClientConfig->id, mClientConfig->id, mServerConfig->getSipId(), NULL, NULL) < 0) {
            LOGI("eXosip_add_authentication_info error");
            return -1;
        }

        return 0;
    }
    int SipClient::request_message_keepalive() {
        char from[1024] = { 0 };
        char to[1024] = { 0 };

        sprintf(from, "sip:%s@%s:%d", mClientConfig->id, mClientConfig->ip, mClientConfig->port);
        sprintf(to, "sip:%s@%s:%d", mServerConfig->getSipId(), mServerConfig->getIp(), mServerConfig->getPort());

        osip_message_t* msg;
        char body[1024] = { 0 };

        sprintf(
            body,
            "<?xml version=\"1.0\" encoding=\"GB2312\" standalone=\"yes\" ?>\r\n"
            "<Notify>\r\n"
            "<CmdType>Keepalive</CmdType>\r\n"
            "<SN>1</SN>\r\n"
            "<DeviceID>%s</DeviceID>\r\n"
            "<Status>OK</Status>\r\n"
            "</Notify>\r\n",
            mClientConfig->id);

        eXosip_message_build_request(mSipCtx, &msg, "MESSAGE", to, from, NULL);
        osip_message_set_body(msg, body, strlen(body));
        osip_message_set_content_type(msg, "Application/MANSCDP+xml");
        eXosip_message_send_request(mSipCtx, msg);

        //        char *s;
        //        size_t len;
        //        osip_message_to_str(msg, &s, &len);
        //         LOGI("send cmd catalog: \n%s", s);

        return 0;
    }

    int SipClient::request_message_catalog() {
        char from[1024] = { 0 };
        char to[1024] = { 0 };

        sprintf(from, "sip:%s@%s:%d", mClientConfig->id, mClientConfig->ip, mClientConfig->port);
        sprintf(to, "sip:%s@%s:%d", mServerConfig->getSipId(), mServerConfig->getIp(), mServerConfig->getPort());

        osip_message_t* msg;
        char body[1024] = { 0 };
        char* s;
        size_t len;

        sprintf(
            body,
            "<?xml version=\"1.0\"?>\r\n"
            "<Query>\r\n"
            "<CmdType>Catalog</CmdType>\r\n"
            "<SN>1</SN>\r\n"
            "<DeviceID>%s</DeviceID>\r\n"
            "</Query>\r\n",
            mServerConfig->getSipId());
        eXosip_message_build_request(mSipCtx, &msg, "MESSAGE", to, from, NULL);
        osip_message_set_body(msg, body, strlen(body));
        osip_message_set_content_type(msg, "Application/MANSCDP+xml");
        eXosip_message_send_request(mSipCtx, msg);

        //osip_message_to_str(msg, &s, &len);
        // LOGI("send cmd catalog: \n%s", s);

        return 0;
    }
    int SipClient::request_register() {
        int ret = -1;
        osip_message_t* msg = NULL;
        char from[1024] = { 0 };
        char contact[1024] = { 0 };
        char proxy[1024] = { 0 };

        if (mRegistered) { // refresh register
            LOGI("刷新注册 mRegisterId=%d", mRegisterId);

            ret = eXosip_register_build_register(mSipCtx, mRegisterId, mServerConfig->getSipExpiry(), &msg);
            if (!ret) {
                LOGE("eXosip_register_build_register error: ret=%d", ret);
                return -1;
            }
        }
        else { // new register
            LOGI("未注册 mRegisterId=%d", mRegisterId);

            sprintf(from, "sip:%s@%s:%d", mClientConfig->id, mClientConfig->ip, mClientConfig->port);
            sprintf(proxy, "sip:%s@%s:%d", mServerConfig->getSipId(), mServerConfig->getIp(), mServerConfig->getPort());
            sprintf(contact, "sip:%s@%s:%d", mClientConfig->id, mClientConfig->ip, mClientConfig->port);
            mRegisterId = eXosip_register_build_initial_register(mSipCtx, from, proxy, contact, mServerConfig->getSipExpiry(), &msg);
            if (mRegisterId <= 0) {
                LOGE("eXosip_register_build_initial_register error: mRegisterId=%d", mRegisterId);
                return -1;
            }
        }
        ret = eXosip_register_send_register(mSipCtx, mRegisterId, msg);
        if (ret) {

            LOGE("eXosip_register_send_register error: ret=%d", ret);
            return ret;
        }
        
        //char* msg_str = NULL;
        //size_t msg_strlen;
        //LOGI("osip_message_to_str 开始分配内存");
        ////这里申请的内存一定要释放,发现在这里申请都会释放不完全
        //ret = osip_message_to_str(msg, &msg_str, &msg_strlen); // 确保调用成功
        //if (ret == 0 && msg_str) {
        //    LOGI("注册请求体: %s", msg_str);
        //}
        //else {
        //    LOGE("osip_message_to_str error: ret=%d", ret);
        //}
        //osip_free(msg_str); // 释放通过 osip_message_to_str 分配的内存
        return ret;
    }
    int SipClient::response_message_answer(eXosip_event_t* evtp, int code) {

        osip_message_t* msg = nullptr;
        int returnCode = eXosip_message_build_answer(mSipCtx, evtp->tid, code, &msg);

        if (returnCode == 0 && msg) {
            eXosip_lock(mSipCtx);
            eXosip_message_send_answer(mSipCtx, evtp->tid, code, msg);
            eXosip_unlock(mSipCtx);
            //        osip_message_free(msg);
        }
        else {
            bool msg_state = false;
            if (msg) {
                msg_state = true;
            }
            LOGE("error: code=%d,returnCode=%d,msg=%d", code, returnCode, msg_state);
        }

        return 0;
    }
    int SipClient::response_message(eXosip_event_t* evtp) {

        osip_body_t* req_body = nullptr;
        osip_message_get_body(evtp->request, 0, &req_body);
        //        LOGI("req_body->body: %s", req_body->body);

        char cmd[64] = { 0 };
        parse_xml(req_body->body, "<CmdType>", false, "</CmdType>", false, cmd);
        LOGI("got message: %s", cmd);

        char SN_c[20] = { 0 }; // 序列号
        int SN = 0;// 序列号
        char DeviceID[100] = { 0 }; // 设备编码
        char DecoderChannelID[100] = { 0 }; // 解码器通道编码
        char PlayUrl[512] = { 0 }; // 源视频地址

        parse_xml(req_body->body, "<SN>", false, "</SN>", false, SN_c);
        parse_xml(req_body->body, "<DeviceID>", false, "</DeviceID>", false, DeviceID);
        parse_xml(req_body->body, "<DecoderChannelID>", false, "</DecoderChannelID>", false, DecoderChannelID);
        parse_xml(req_body->body, "<PlayUrl>", false, "</PlayUrl>", false, PlayUrl);


        LOGI("DeviceID:%s", DeviceID);
        LOGI("DecoderChannelID:%s", DecoderChannelID);
        SN = std::stoi(SN_c);

        if (!strcmp(cmd, "Catalog")) {
            this->response_message_answer(evtp, 200);
			char from[1024] = { 0 };
			char to[1024] = { 0 };

			sprintf(from, "sip:%s@%s:%d", mClientConfig->id, mClientConfig->ip, mClientConfig->port);
			sprintf(to, "sip:%s@%s:%d", mServerConfig->getSipId(), mServerConfig->getIp(), mServerConfig->getPort());

			osip_message_t* msg;
			char body[1024] = { 0 };
			char* s;
			size_t len;

			sprintf(
				body,
				"<?xml version=\"1.0\"?>\r\n"
				"<Response>\r\n"
				"<CmdType>Catalog</CmdType>\r\n"
				"<SN>%d</SN>\r\n"
				"<DeviceID>%s</DeviceID>\r\n"
				"<SumNum>1</SumNum>\r\n"
				"<DeviceList Num=\"1\">\r\n"
				"<Item>\r\n"
				"<DeviceID>%s</DeviceID>\r\n"
				"<Name>%s</Name>\r\n"
				"<Manufacturer>%s</Manufacturer>\r\n"
				"<Model>%s</Model>\r\n"
				"<Owner>%s</Owner>\r\n"
				"<CivilCode>%s</CivilCode>\r\n"
				"<Address>%s</Address>\r\n"
				"<Parental>%d</Parental>\r\n"
				"<SafetyWay>%d</SafetyWay>\r\n"
				"<RegisterWay>%d</RegisterWay>\r\n"
				"<Secrecy>%d</Secrecy>\r\n"
				"<Longitude>%f</Longitude>\r\n"
				"<Latitude>%f</Latitude>\r\n"
				"<Status>%s</Status>\r\n"
				"</Item>\r\n"
				"</DeviceList>\r\n"
				"</Response>\r\n",
				SN,
				mClientConfig->id,
				//mServerConfig->getSipId(),
				mClientConfig->id, "IPC", "Hikvision", "IP Camera", "Owner", "CivilCode",
				"Address", 0, 0, 1, 0, 114.0, 23.0, "OK");


			eXosip_message_build_request(mSipCtx, &msg, "MESSAGE", to, from, NULL);
			osip_message_set_body(msg, body, strlen(body));
			osip_message_set_content_type(msg, "Application/MANSCDP+xml");
			eXosip_message_send_request(mSipCtx, msg);
			//osip_message_to_str(msg, &s, &len);
			//LOGI("send cmd catalog: \n%s", s);
   //         osip_free(s);
        }
        else {
            this->response_message_answer(evtp, 200);

        }

        return 0;
    }
    int SipClient::response_invite(eXosip_event_t* evtp) {
        char* username = evtp->request->to->url->username;//对应摄像头的DeviceID
        char* CallID = evtp->request->call_id->number;
        LOGI("username:%s", username);
        LOGI("CallID:%s", CallID);

        osip_message_t* answer = nullptr;
        eXosip_lock(mSipCtx);
        //eXosip_call_send_answer(mSipCtx, evtp->tid, 180, nullptr);
        int ret = eXosip_call_build_answer(mSipCtx, evtp->tid, 200, &answer);
        if (ret != 0) {
            eXosip_call_send_answer(mSipCtx, evtp->tid, 400, nullptr);
            LOGE("camera: %s eXosip_call_build_answer error", username);
        }
        else {

            // 采用exosip的函数解析sdp
            /*
            printf("-----------exosip parse start-----------\n");
            sdp_message_t *remote_sdp = eXosip_get_remote_sdp(mSipCtx, evtp->did);
            if(remote_sdp){
                sdp_media_t *video_sdp = eXosip_get_video_media(remote_sdp);
                if (video_sdp) {
                    int pos = 0;
                    char *video_port = video_sdp->m_port; // audio_port
                    for (int i = 0; i < video_sdp->a_attributes.nb_elt; i++)
                    {
                        sdp_attribute_t *attr = (sdp_attribute_t *)osip_list_get(&video_sdp->a_attributes, i);
                        printf("1-%s : %s\n", attr->a_att_field, attr->a_att_value);
                    }
                    while (!osip_list_eol(&(remote_sdp->a_attributes), pos)) {
                        sdp_attribute_t *at;
                        at = (sdp_attribute_t *)osip_list_get(&remote_sdp->a_attributes, pos);
                        printf(
                            "2-%s : %s\n", at->a_att_field,
                            at->a_att_value); // 这里解释了为什么在SDP消息体中属性a里面存放必须是两列
                        pos++;
                    }
                    while (!osip_list_eol(&(remote_sdp->m_medias), pos)) {
                        sdp_attribute_t *at;

                        at = (sdp_attribute_t *)osip_list_get(&remote_sdp->m_medias, pos);
                        printf(
                            "3-%s : %s\n", at->a_att_field,
                            at->a_att_value); // 这里解释了为什么在SDP消息体中属性a里面存放必须是两列

                        pos++;
                    }
                }
            }
            printf("-----------exosip parse end-----------\n");
            */


            printf("-----------my parse start-----------\n");
            int trackSize = 0;
            // 下面解析SDP的方式只适合一个媒体流，所有如果同时包含音频和视频流，需要注意！！！
            // 采用自定义的方式解析sdp
            osip_body_t* req_body = nullptr;
            osip_message_get_body(evtp->request, 0, &req_body);

            /*获取远端和本地的SDP*/
            sdp_message_t* SdpRomte = NULL;
            osip_body_t* RqtBody = NULL;
            osip_message_get_body(evtp->request, 0, &RqtBody);
            sdp_message_init(&SdpRomte);
            sdp_message_parse(SdpRomte, RqtBody->body);
            std::string ServerProto(sdp_message_m_proto_get(SdpRomte, 0));

            std::vector<std::string> lineArray = split(req_body->body, "\n");
            for (auto& line : lineArray) {
                printf(">>>>>>%s\n", line.data());

                if (!strncmp(line.data(), "c=IN", strlen("c=IN"))) {
                    // example: c=IN IP4 192.168.8.91
                    if (sscanf(line.data(), "c=IN IP4 %s ", &track.peerIp) != 1) {
                        LOGE("parse line error:%s", line.data());
                        break;
                    }
                }
				if (!strncmp(line.data(), "y=", strlen("y="))) {
					// example: c=IN IP4 192.168.8.91
					if (sscanf(line.data(), "y=%s ", &track.peerysource) != 1) {
						LOGE("parse line error:%s", line.data());
						break;
					}
					printf("-----------my parse y=%s-----------\n", track.peerysource);
				}
                if (!strncmp(line.data(), "m=", strlen("m="))) {
                    // example: m=video 15060 TCP/RTP/AVP 96
                    if (sscanf(line.data(), "m=%s %d %s %s ", &track.mediaType, &track.peerRtpPort, &track.peerRtpTransport, &track.peerStreamType) != 4) {
                        LOGE("parse line error:%s", line.data());
                        break;
                    }
                    else {
                        // success
                        trackSize++;
                    }

                }
            }
            printf("-----------my parse end-----------\n");

            LOGI("trackSize=%d", trackSize);

            //还有一点需要注意，这个设置：a=sendonly
            char sdpBuf[2048];
            snprintf(
                sdpBuf, sizeof(sdpBuf),
                "v=0\r\n"
				"o=%s 0 0 IN IP4 %s\r\n"
                "s=Play\r\n"
                "c=IN IP4 %s\r\n"
                "t=0 0\r\n"
                "m=video %d %s 96\r\n"
                "a=sendonly\r\n"
                "a=rtpmap:96 PS/90000\r\n"
				"y=%s\r\n",
				mClientConfig->id,
                mClientConfig->ip, mClientConfig->ip,
                mClientConfig->localRtpPort, ServerProto.c_str(), track.peerysource);// 

            osip_message_set_body(answer, sdpBuf, strlen(sdpBuf));
            osip_message_set_content_type(answer, "application/sdp");
            int ret = eXosip_call_send_answer(mSipCtx, evtp->tid, 200, answer);
			printf("ret = %d \n response_invite: \n%s", ret, sdpBuf);
            sdp_message_free(SdpRomte);
        }
        
        eXosip_unlock(mSipCtx);
        //osip_message_free(answer);
        //sdp_message_free(answer);
        return 0;
    }

    int SipClient::response_ack(eXosip_event_t* evtp) {
        char* username = evtp->request->to->url->username;//对应摄像头的DeviceID
        char* CallID = evtp->request->call_id->number;
        LOGI("接收到信令服务的ACK，开始ps over rtp 推流");
        printf("username:%s\n", username);
        printf("CallID:%s\n", CallID);
        /*获取远端和本地的SDP*/
        sdp_message_t* SdpRomte = NULL;
        //sdp_message_t* SdpLocal = NULL;
        osip_body_t* RqtBody = NULL;
        //osip_body_t* RpeBody = NULL;
        osip_message_get_body(evtp->request, 0, &RqtBody);
        sdp_message_init(&SdpRomte);
        sdp_message_parse(SdpRomte, RqtBody->body);

        //osip_message_get_body(evtp->response, 0, &RpeBody);
        //sdp_message_init(&SdpLocal);
        //sdp_message_parse(SdpLocal, RpeBody->body);
        std::string ServerProto(sdp_message_m_proto_get(SdpRomte, 0));

        // 正式开始推流
        if(mRtpSendPs){
            mRtpSendPs->stop();
            delete mRtpSendPs;
            mRtpSendPs = nullptr;
        }
		
        mRtpSendPs = new RtpSendPs(mServerConfig->getIp(), track.peerRtpPort,mClientConfig->localRtpPort, mrtspurl, ServerProto);
        mRtpSendPs->start();
        sdp_message_free(SdpRomte);
        return 0;
    }

    int SipClient::response_bye(eXosip_event_t* evtp) {
        char* username = evtp->request->to->url->username;//对应摄像头的DeviceID
        char* CallID = evtp->request->call_id->number;
        LOGI("接收到信令服务的BYE，停止ps over rtp 推流");
        LOGI("username:%s", username);
        LOGI("CallID:%s", CallID);
        // 停止推流
        if(mRtpSendPs){
            mRtpSendPs->stop();
            delete mRtpSendPs;
            mRtpSendPs = nullptr;
        }

        return 0;
    }
    int SipClient::sip_event_handle(eXosip_event_t* evtp) {
		LOGI("type=%d -----------------------------", evtp->type);
        switch (evtp->type) {
        case EXOSIP_MESSAGE_NEW:
            LOGI("EXOSIP_MESSAGE_NEW");

            if (MSG_IS_REGISTER(evtp->request)) {
                LOGI("MSG_IS_REGISTER，不应该出现的响应，请排查问题");

            }
            else if (MSG_IS_MESSAGE(evtp->request)) {
                this->response_message(evtp);
            }
            else {
                LOGI("未定义类型的MESSAGE");

                this->dump_request(evtp);

                /*
                // 可能会出现的请求
                BYE sip:00662800000403000001@192.168.8.200:5060 SIP/2.0
                Via: SIP/2.0/UDP 192.168.8.114:5060;branch=z9hG4bK695c5ff8b5c014866ffc6a554c242a6d
                From: <sip:00662800000401000001@0066280000>;tag=185326220
                To: <sip:00662802002006028104@0066280000>;tag=2009556327
                Call-ID: 05a7fc88c30878338ff311a788e9cefa@192.168.8.114
                CSeq: 185 BYE
                Max-forwards: 70
                Content-Length: 0
                */
            }
            break;
        case EXOSIP_CALL_ANSWERED:
            LOGI("EXOSIP_CALL_ANSWERED type=%d:这里应该主动发送ACK之后的回复", evtp->type);
            this->dump_request(evtp);
            this->dump_response(evtp);
            break;
        case EXOSIP_REGISTRATION_FAILURE:
            LOGI("EXOSIP_REGISTRATION_FAILURE type=%d", evtp->type);
            LOGI("mRegistered=%d,mRegisterId=%d", mRegistered, mRegisterId);
            this->mRegistered = false;

            if (eXosip_add_authentication_info(mSipCtx, mClientConfig->id, mClientConfig->id, mServerConfig->getSipPass(), NULL, NULL) < 0) {
                LOGI("eXosip_add_authentication_info error");
            }
            break;
        case EXOSIP_REGISTRATION_SUCCESS:
            LOGI("EXOSIP_REGISTRATION_SUCCESS type=%d", evtp->type);
            this->mRegistered = true;
            LOGI("mRegistered=%d,mRegisterId=%d", mRegistered, mRegisterId);

            //                this->dump_request(evtp);
            //                this->request_message_keepalive();
            break;
        case EXOSIP_CALL_INVITE:
            LOGI("EXOSIP_CALL_INVITE type=%d: 接收到对方发送了Invite请求", evtp->type);
            //                this->dump_request(evtp);
            //                this->dump_response(evtp);
            this->response_invite(evtp);
			//this->response_ack(evtp);
            break;
        case EXOSIP_CALL_ACK:
            LOGI("EXOSIP_CALL_ACK type=%d: 收到来自对方ACK请求。准备国标推流。", evtp->type);
            dump_request(evtp);
            this->response_ack(evtp);
            break;
        case EXOSIP_IN_SUBSCRIPTION_NEW:
            LOGI("EXOSIP_IN_SUBSCRIPTION_NEW type=%d", evtp->type);
            dump_request(evtp);
            break;
        case EXOSIP_CALL_NOANSWER: {
            LOGI("EXOSIP_IN_SUBSCRIPTION_NEW type=%d", evtp->type);
            break;
        }
        case EXOSIP_CALL_MESSAGE_NEW://14
        {
            LOGI("EXOSIP_CALL_MESSAGE_NEW type=%d", evtp->type);
            this->dump_request(evtp);
            this->dump_response(evtp);
            break;
        }
        case EXOSIP_CALL_CLOSED://21
        {
            LOGI("EXOSIP_CALL_CLOSED type=%d", evtp->type);
            this->dump_request(evtp);
            this->dump_response(evtp);
            this->response_bye(evtp);
            break;
        }
        case EXOSIP_CALL_RELEASED://22
        {
            LOGI("EXOSIP_CALL_RELEASED type=%d: Bye确认", evtp->type);
            break;
        }
        case EXOSIP_MESSAGE_REQUESTFAILURE:
            LOGI("EXOSIP_MESSAGE_REQUESTFAILURE type=%d", evtp->type);
            LOGI("evtp->textinfo= '%s' ", evtp->textinfo);
            if (evtp->ack) {
                char* ack_str;
                size_t ack_str_len;
                /*osip_message_to_str(evtp->ack, &ack_str, &ack_str_len);
                LOGI("ack_str=%s", ack_str);*/
            }
            this->dump_request(evtp);
            this->dump_response(evtp);

            break;
        case EXOSIP_MESSAGE_ANSWERED:
            LOGI("EXOSIP_MESSAGE_ANSWERED type=%d: 接收到来自对应的MESSAGE请求。", evtp->type);
            break;
        default: LOGI("type=%d unknown ", evtp->type); break;
        }

        return 0;
    }


    int SipClient::parse_xml(const char* data, const char* s_mark, bool with_s_make, const char* e_mark, bool with_e_make, char* dest) {
        const char* satrt = strstr(data, s_mark);

        if (satrt != NULL) {
            const char* end = strstr(satrt, e_mark);
            if (end != NULL) {
                int s_pos = with_s_make ? 0 : strlen(s_mark);
                int e_pos = with_e_make ? strlen(e_mark) : 0;

                strncpy(dest, satrt + s_pos, (end + e_pos) - (satrt + s_pos));
            }
            return 0;
        }
        return -1;
    }
    void SipClient::dump_request(eXosip_event_t* evt) {
        char* s;
        size_t len;
        osip_message_to_str(evt->request, &s, &len);
        LOGI("\n打印请求包开始\ntype=%d\n%s\n打印请求包结束\n", evt->type, s);
        osip_free(s);

    }
    void SipClient::dump_response(eXosip_event_t* evt) {
        char* s;
        size_t len;
        osip_message_to_str(evt->response, &s, &len);
        LOGI("\n打印响应包开始\ntype=%d\n%s\n打印响应包结束\n", evt->type, s);
        osip_free(s);
    }
}